﻿namespace SimpleMath
{
    using System;
    using System.Diagnostics;

    public class SimpleMath
    {
        public static void DisplayExecutionTime(Action action)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            action();
            stopwatch.Stop();
            Console.WriteLine(stopwatch.Elapsed);
        }

        private const int OperationsCount = 10000000;

        public static void Main(string[] args)
        {
            Console.WriteLine("Add");
            Console.WriteLine("===");
            Console.Write("integers:\t");
            DisplayExecutionTime(() => AddTests.AddNumber(3, OperationsCount));

            Console.Write("longs:\t\t");
            DisplayExecutionTime(() => AddTests.AddNumber(3L, (long)OperationsCount));

            Console.Write("floats:\t\t");
            DisplayExecutionTime(() => AddTests.AddNumber(3f, (float)OperationsCount));

            Console.Write("doubles:\t");
            DisplayExecutionTime(() => AddTests.AddNumber(3.0, (double)OperationsCount));

            Console.Write("decimals:\t");
            DisplayExecutionTime(() => AddTests.AddNumber(3m, (decimal)OperationsCount));

            Console.WriteLine();
            Console.WriteLine("Subtract");
            Console.WriteLine("========");
            Console.Write("integers:\t");
            DisplayExecutionTime(() => SubtractTests.SubtractNumber(3, OperationsCount));

            Console.Write("longs:\t\t");
            DisplayExecutionTime(() => SubtractTests.SubtractNumber(3L, (long)OperationsCount));

            Console.Write("floats:\t\t");
            DisplayExecutionTime(() => SubtractTests.SubtractNumber(3f, (float)OperationsCount));

            Console.Write("doubles:\t");
            DisplayExecutionTime(() => SubtractTests.SubtractNumber(3.0, (double)OperationsCount));

            Console.Write("decimals:\t");
            DisplayExecutionTime(() => SubtractTests.SubtractNumber(3m, (decimal)OperationsCount));

            Console.WriteLine();
            Console.WriteLine("Increment");
            Console.WriteLine("=========");
            Console.Write("integers:\t");
            DisplayExecutionTime(() => AddTests.AddNumber(1, OperationsCount));

            Console.Write("longs:\t\t");
            DisplayExecutionTime(() => AddTests.AddNumber(1L, (long)OperationsCount));

            Console.Write("floats:\t\t");
            DisplayExecutionTime(() => AddTests.AddNumber(1f, (float)OperationsCount));

            Console.Write("doubles:\t");
            DisplayExecutionTime(() => AddTests.AddNumber(1.0, (double)OperationsCount));

            Console.Write("decimals:\t");
            DisplayExecutionTime(() => AddTests.AddNumber(1m, (decimal)OperationsCount));

            Console.WriteLine();
            Console.WriteLine("Multiply");
            Console.WriteLine("========");
            Console.Write("integers:\t");
            DisplayExecutionTime(() => MultiplyTest.MultiplyNumber(3, OperationsCount));

            Console.Write("longs:\t\t");
            DisplayExecutionTime(() => MultiplyTest.MultiplyNumber(3L, (long)OperationsCount));

            Console.Write("floats:\t\t");
            DisplayExecutionTime(() => MultiplyTest.MultiplyNumber(3f, (float)OperationsCount));

            Console.Write("doubles:\t");
            DisplayExecutionTime(() => MultiplyTest.MultiplyNumber(3.0, (double)OperationsCount));

            Console.Write("decimals:\t");
            DisplayExecutionTime(() => MultiplyTest.MultiplyNumber(3m, (decimal)OperationsCount));

            Console.WriteLine();
            Console.WriteLine("Divide");
            Console.WriteLine("======");
            Console.Write("integers:\t");
            DisplayExecutionTime(() => DivideTests.DivideNumber(3, OperationsCount));

            Console.Write("longs:\t\t");
            DisplayExecutionTime(() => DivideTests.DivideNumber(3L, (long)OperationsCount));

            Console.Write("floats:\t\t");
            DisplayExecutionTime(() => DivideTests.DivideNumber(3f, (float)OperationsCount));

            Console.Write("doubles:\t");
            DisplayExecutionTime(() => DivideTests.DivideNumber(3.0, (double)OperationsCount));

            Console.Write("decimals:\t");
            DisplayExecutionTime(() => DivideTests.DivideNumber(3m, (decimal)OperationsCount));
        }
    }
}